﻿using AutoMapper;
using Newtonsoft.Json;
using WMS.FC.Domain.DataTransferObject.Menu;
using WMS.FC.Domain.DataTransferObject.Technology;
using WMS.FC.Domain.DomainObject.Menu;
using WMS.FC.Domain.DomainObject.Station;
using WMS.FC.Domain.DomainObject.System;
using WMS.FC.Domain.DomainObject.Tasks;
using WMS.FC.Domain.DomainObject.Technology;
using WMS.FC.Domain.DomainObject.Tray;
using WMS.FC.Domain.DomainObject.User;
using WMS.FC.Domain.PersistenceObject.Business;
using WMS.FC.Domain.PersistenceObject.System;
using WMS.FC.Domain.ValueObject.Menu;
using WMS.FC.Domain.ValueObject.System;
using WMS.FC.Domain.ValueObject.Technology;
using WMS.FC.Domain.ValueObject.User;
using WMS.FC.Domain.ValueObject.WCS;
using WMS.FC.Infrastructure.Common;

namespace WMS.FC.Infrastructure.Register
{
    public class AutoMapperRegister : Profile
    {

        public AutoMapperRegister()
        {
            CreateMap();
        }

        private void CreateMap()
        {
            CreateSystemMap();
            CreateTrayMap();
            CreateTaskMap();
            CreateTechnologyMap();
        }

        private void CreateSystemMap()
        {
            CreateMap<DomainObjectBase, ValueObjectBase>();

            CreateMap<UserPO, UserDO>().ForMember(dest => dest.Password, option => option.MapFrom(source => EncryptHelper.Decrypt(source.Password, EncryptHelper.KEY, EncryptHelper.IV)));
            CreateMap<UserDO, UserVO>()
                .ForMember(dest => dest.UserName, option => option.MapFrom(source => source.Name))
                .ForMember(dest => dest.Token, option => option.MapFrom(source => EncryptHelper.Encrypt(JsonConvert.SerializeObject(new UserInfo()
                {
                    UserAccount = source.Account,
                    UserName = source.Name,
                    LastRequestTime = DateTime.Now,
                }), EncryptHelper.KEY, EncryptHelper.IV)));

            CreateMap<MenuPO, MenuDO>()
                .ForMember(dest => dest.Id, option => option.MapFrom(source => source.Id))
                .ForMember(dest => dest.Name, option => option.MapFrom(source => source.NameCN))
                .ForMember(dest => dest.Icon, option => option.MapFrom(source => source.Icon));

            CreateMap<MenuDO, MenuVO>()
                 .ForMember(dest => dest.Id, option => option.MapFrom(source => source.Id))
                 .ForMember(dest => dest.Name, option => option.MapFrom(source => source.Name))
                 .ForMember(dest => dest.Icon, option => option.MapFrom(source => $"/image/{source.Icon}"))
                 .ForMember(dest => dest.Url, option => option.MapFrom(source => source.Url))
                 .ForMember(dest => dest.Children, option => option.MapFrom(source => source.Children));

            CreateMap<MenuPO, MenuConfigDO>()
                .ForMember(dest => dest.NameCN, option => option.MapFrom(source => source.NameCN))
                .ForMember(dest => dest.NameEN, option => option.MapFrom(source => source.NameEN))
                .ForMember(dest => dest.Icon, option => option.MapFrom(source => source.Icon))
                .ForMember(dest => dest.TypeCode, option => option.MapFrom(source => source.TypeCode))
                .ForMember(dest => dest.MenuPositionCode, option => option.MapFrom(source => source.MenuPositionCode))
                .ForMember(dest => dest.SortNumber, option => option.MapFrom(source => source.SortNumber))
                .ForMember(dest => dest.Url, option => option.MapFrom(source => source.Url))
                .ForMember(dest => dest.Sql, option => option.MapFrom(source => source.Sql))
                .ForMember(dest => dest.ColumnList, option => option.MapFrom(source => string.IsNullOrWhiteSpace(source.ConfigJson) ? new List<ColumnDO>() : JsonConvert.DeserializeObject<List<ColumnDO>>(source.ConfigJson)))
                .ForMember(dest => dest.ButtonList, option => option.MapFrom(source => source.SubMenu.Where(menu => menu.TypeCode != "MenuType_Menu").OrderBy(menu => menu.SortNumber).Select(menu => new MenuConfigDO()
                {
                    Id = menu.Id,
                    NameCN = menu.NameCN,
                    NameEN = menu.NameEN,
                    Icon = menu.Icon,
                    TypeCode = menu.TypeCode,
                    MenuPositionCode = menu.MenuPositionCode,
                    SortNumber = menu.SortNumber,
                    Url = menu.Url,
                    Sql = menu.Sql,
                    ColumnList = string.IsNullOrWhiteSpace(menu.ConfigJson) ? new List<ColumnDO>() : JsonConvert.DeserializeObject<List<ColumnDO>>(menu.ConfigJson)!
                }).ToList()));

            CreateMap<ColumnRuleDO, ColumnRuleVO>().ReverseMap();
            CreateMap<ColumnDO, ColumnVO>().ReverseMap();
            CreateMap<MenuConfigDO, MenuConfigVO>();

            CreateMap<EditMenuDTO, MenuConfigDO>()
                .ForMember(dest => dest.Id, option => option.MapFrom(source => string.IsNullOrWhiteSpace(source.Id) ? 0 : Convert.ToInt64(source.Id)))
                .ForMember(dest => dest.NameCN, option => option.MapFrom(source => source.NameCN))
                .ForMember(dest => dest.NameEN, option => option.MapFrom(source => source.NameEN))
                .ForMember(dest => dest.Icon, option => option.MapFrom(source => source.Icon))
                .ForMember(dest => dest.TypeCode, option => option.MapFrom(source => source.TypeCode))
                .ForMember(dest => dest.MenuPositionCode, option => option.MapFrom(source => source.MenuPositionCode))
                .ForMember(dest => dest.SortNumber, option => option.MapFrom(source => source.SortNumber))
                .ForMember(dest => dest.Url, option => option.MapFrom(source => source.Url))
                .ForMember(dest => dest.Sql, option => option.MapFrom(source => source.Sql))
                .ForMember(dest => dest.ColumnList, option => option.MapFrom(source => source.ColumnList));

            CreateMap<MenuConfigDO, MenuPO>()
                .ForMember(dest => dest.NameCN, option => option.MapFrom(source => source.NameCN))
                .ForMember(dest => dest.NameEN, option => option.MapFrom(source => source.NameEN))
                .ForMember(dest => dest.Icon, option => option.MapFrom(source => source.Icon))
                .ForMember(dest => dest.TypeCode, option => option.MapFrom(source => source.TypeCode))
                .ForMember(dest => dest.MenuPositionCode, option => option.MapFrom(source => source.MenuPositionCode))
                .ForMember(dest => dest.SortNumber, option => option.MapFrom(source => source.SortNumber))
                .ForMember(dest => dest.Url, option => option.MapFrom(source => source.Url))
                .ForMember(dest => dest.Sql, option => option.MapFrom(source => source.Sql))
                .ForMember(dest => dest.ConfigJson, option => option.MapFrom(source => JsonConvert.SerializeObject(source.ColumnList)))
                .ForMember(dest => dest.Id, option => option.Ignore())
                .ForMember(dest => dest.CreateDate, option => option.Ignore())
                .ForMember(dest => dest.CreatedBy, option => option.Ignore())
                .ForMember(dest => dest.ModifiedBy, option => option.Ignore())
                .ForMember(dest => dest.ModifyDate, option => option.Ignore())
                .ForMember(dest => dest.ModifyIp, option => option.Ignore())
                .ForMember(dest => dest.ParentId, option => option.Ignore())
                .ForMember(dest => dest.IsDeleted, option => option.Ignore())
                .ForMember(dest => dest.Timestamp, option => option.Ignore());

            CreateMap<ColumnRuleDO, ColumnRuleVO>()
                .ForMember(dest => dest.RegExp, option => option.MapFrom(source => source.RegExp))
                .ForMember(dest => dest.Message, option => option.MapFrom(source => source.Message));

            CreateMap<ColumnDO, ElColumnVO>()
                .ForMember(dest => dest.Prop, option => option.MapFrom(source => source.Field))
                .ForMember(dest => dest.Label, option => option.MapFrom(source => source.NameCN))
                .ForMember(dest => dest.Width, option => option.MapFrom(source => source.Width))
                .ForMember(dest => dest.IsReadonly, option => option.MapFrom(source => source.IsReadonly))
                .ForMember(dest => dest.IsHidden, option => option.MapFrom(source => source.IsHidden))
                .ForMember(dest => dest.IsSearchable, option => option.MapFrom(source => source.IsSearchable))
                .ForMember(dest => dest.BindField, option => option.MapFrom(source => ((source.ControlTypeCode == "ControlType_Select" || source.ControlTypeCode == "ControlType_MultiSelect") && source.DataSource.Split(";", StringSplitOptions.RemoveEmptyEntries).Length > 1) ? source.DataSource.Split(";", StringSplitOptions.RemoveEmptyEntries)[1] : ""))
                .ForMember(dest => dest.DefaultValue, option => option.MapFrom(source => (source.ControlTypeCode == "ControlType_Select" || source.ControlTypeCode == "ControlType_MultiSelect") ? "" : source.DataSource))
                .ForMember(dest => dest.ControlTypeCode, option => option.MapFrom(source => source.ControlTypeCode))
                .ForMember(dest => dest.Rules, option => option.MapFrom(source => source.Rules));

            CreateMap<MenuConfigDO, PageConfigVO>()
                .ForMember(dest => dest.Id, option => option.MapFrom(source => source.Id))
                .ForMember(dest => dest.Name, option => option.MapFrom(source => source.NameCN))
                .ForMember(dest => dest.Icon, option => option.MapFrom(source => source.Icon))
                .ForMember(dest => dest.TypeCode, option => option.MapFrom(source => source.TypeCode))
                .ForMember(dest => dest.MenuPositionCode, option => option.MapFrom(source => source.MenuPositionCode))
                .ForMember(dest => dest.Url, option => option.MapFrom(source => source.Url))
                .ForMember(dest => dest.ColumnList, option => option.MapFrom(source => source.ColumnList))
                .ForMember(dest => dest.ButtonList, option => option.Ignore());

            CreateMap<PageConfigDO, PageConfigVO>()
                .ForMember(dest => dest.Id, option => option.MapFrom(source => source.MenuConfig.Id.ToString()))
                .ForMember(dest => dest.Name, option => option.MapFrom(source => source.MenuConfig.NameCN))
                .ForMember(dest => dest.Icon, option => option.MapFrom(source => source.MenuConfig.Icon))
                .ForMember(dest => dest.TypeCode, option => option.MapFrom(source => source.MenuConfig.TypeCode))
                .ForMember(dest => dest.MenuPositionCode, option => option.MapFrom(source => source.MenuConfig.MenuPositionCode))
                .ForMember(dest => dest.Url, option => option.MapFrom(source => source.MenuConfig.Url))
                .ForMember(dest => dest.ColumnList, option => option.MapFrom(source => source.MenuConfig.ColumnList))
                .ForMember(dest => dest.ButtonList, option => option.MapFrom(source => source.MenuConfig.ButtonList))
                .ForMember(dest => dest.Dictionary, option => option.MapFrom(source => source.Dictionary));

            CreateMap<PageDataDO, PageDataVO>()
                .ForMember(dest => dest.Total, option => option.MapFrom(source => source.Total))
                .ForMember(dest => dest.Rows, option => option.MapFrom(source => JsonConvert.SerializeObject(source.Rows, new JsonSerializerSettings()
                {
                    ContractResolver = new LowercaseContractResolver(),
                    NullValueHandling = NullValueHandling.Ignore,
                    DateFormatString = "yyyy-MM-dd HH:mm:ss",
                    Converters = new List<JsonConverter>()
                    {
                        new ToStringJsonConverter()
                    }
                })));

            CreateMap<DictionaryDO, DictionaryVO>();
        }

        private void CreateTrayMap()
        {
            CreateMap<TrayDO, WcsTrayVO>()
               .ForMember(dest => dest.TrayBarcode, option => option.MapFrom(source => source.CurrentTray.Barcode))
               .ForMember(dest => dest.IsNeedFakeCell, option => option.MapFrom(source => source.CurrentTechnologyProcess!.IsNeedFakeCell))
               .ForMember(dest => dest.CellList, option => option.MapFrom(source => source.CellList.Select(cell => new CellVO()
               {
                   CellPosition = cell.CellPosition!.Value,
                   CellBarcode = cell.Barcode,
                   IsEmpty = string.IsNullOrWhiteSpace(cell.Barcode),
                   IsNg = !string.IsNullOrWhiteSpace(cell.NgCode)
               })));

            CreateMap<TargetStationDO, TargetStationVO>()
                .ForMember(dest => dest.TrayBarcode1, option => option.MapFrom(source => source.Tray.TrayList!.Count > 0 ? source.Tray.TrayList[0].Barcode : ""))
                .ForMember(dest => dest.TrayBarcode2, option => option.MapFrom(source => source.Tray.TrayList!.Count > 1 ? source.Tray.TrayList[1].Barcode : ""))
                .ForMember(dest => dest.TrayBarcode3, option => option.MapFrom(source => source.Tray.TrayList!.Count > 2 ? source.Tray.TrayList[2].Barcode : ""))
                .ForMember(dest => dest.TargetStation, option => option.MapFrom(source => source.TargetStationCode))
                .ForMember(dest => dest.IsNg, option => option.MapFrom(source => source.IsNg))
                .ForMember(dest => dest.IsFull, option => option.MapFrom(source => source.IsFull))
                .ForMember(dest => dest.IsException, option => option.MapFrom(source => source.IsException))
                .ForMember(dest => dest.GoodsType, option => option.MapFrom(source => source.GoodsType));
        }

        private void CreateTaskMap()
        {
            CreateMap<TaskDO, TaskVO>()
                .ForMember(dest => dest.TaskCode, option => option.MapFrom(source => source.Task!.Code))
                .ForMember(dest => dest.TrayBarcode1, option => option.MapFrom(source => source.Tray!.TrayList!.Count > 0 ? source.Tray.TrayList[0].Barcode : ""))
                .ForMember(dest => dest.TrayBarcode2, option => option.MapFrom(source => source.Tray!.TrayList!.Count > 1 ? source.Tray.TrayList[1].Barcode : ""))
                .ForMember(dest => dest.TrayBarcode3, option => option.MapFrom(source => source.Tray!.TrayList!.Count > 2 ? source.Tray.TrayList[2].Barcode : ""))
                .ForMember(dest => dest.StartPoint, option => option.MapFrom(source => source.Task!.StartPointCdoe))
                .ForMember(dest => dest.EndPoint, option => option.MapFrom(source => source.Task!.EndPointCode))
                .ForMember(dest => dest.EquipmentCode, option => option.MapFrom(source => source.Task!.EquipmentCode))
                .ForMember(dest => dest.GoodsType, option => option.MapFrom(source => $"{(source.Task!.TotalCellCount == 0 ? "1" : "2")}{source.Tray!.TrayList!.Count}"));
        }

        private void CreateTechnologyMap()
        {
            CreateMap<TechnologyRoutePO, TechnologyRouteDO>();
            CreateMap<TechnologyRouteDO, TechnologyRouteVO>();
            CreateMap<EditTechnologyRouteDTO, TechnologyRouteDO>();
            CreateMap<TechnologyRouteProcessPO, TechnologyRouteProcessDO>();
            CreateMap<TechnologyRouteProcessDO, TechnologyRouteProcessVO>();
            CreateMap<EditTechnologyRouteProcessDTO, TechnologyRouteProcessDO>();

            CreateMap<TechnologyRouteDO, TechnologyRoutePO>()
               .ForMember(dest => dest.Id, option => option.Ignore())
               .ForMember(dest => dest.SortNumber, option => option.Ignore());

            CreateMap<TechnologyRouteProcessDO, TechnologyRouteProcessPO>()
                .ForMember(dest => dest.Id, option => option.Ignore());
        }
    }
}
